<!DOCTYPE html><html class="appearance-auto" lang="zh-CN"><head><meta charset="UTF-8"><title>【Spring源码解析系列】 BeanFactoryPostProcessor</title><meta name="description" content="用创业者心态做好每一件事情！"><meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, initial-scale=1"><!-- Google Analytics --><!-- End Google Analytics -->
<!-- Baidu Analytics --><!-- End Baidu Analytics --><link rel="icon" href="/blog/images/favicon.png"><link rel="stylesheet" href="/blog/style/common/bulma.css"><link rel="stylesheet" href="/blog/style/base.css"><link rel="stylesheet" href="/blog/style/common/helper.css"><script src="/blog/js/common.js"></script><link rel="stylesheet" href="/blog/style/post.css"><link rel="stylesheet" href="/blog/style/themes/highlight-theme-light.css"><script src="/blog/js/highlight.pack.js"></script><meta name="description" content="
本文主要讲述Spring三大扩展功能之：BeanFactoryPostProcessor


定义BeanFactory类型的后置处理器
使用目的在BeanFactory标准初始化之后来定制修改BeanFactory的bean内容
工作时机此时所有Bean的定义被加载进BeanFactory中，但是Bean的实例未完成创建；
示例1、自定义BeanPostProcessor/**
 * 自定义BeanPostProcessor实现类
 * BeanPostProcessor接口的作用是：
 * 我们可以通过该接口中的方法在bean实例化、配置以及其他初始化方法前后添加一些我们自己的逻辑
 */
public class MyBeanPostProcessor implements BeanPostProc.."><!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 5.4.1"><link rel="alternate" href="/blog/atom.xml" title="janedler's blog" type="application/atom+xml">
</head><body class="is-flex is-flex-direction-column"><header class="header-widget is-flex-shrink-0 is-hidden-mobile"><div class="container is-fullhd is-flex is-justify-content-space-between is-align-items-center is-full-height"><section class="is-hidden-mobile is-flex-shrink-0"><h2><a href="/blog/">田园牧歌(*︶*)'s blog</a></h2></section><h3 class="is-hidden-mobile is-family-serif is-full-height is-flex is-align-items-center is-flex-shrink-0"><div class="is-full-height" id="postTopic"><p class="is-full-height is-flex-shrink-0 is-flex is-align-items-center is-justify-content-center">【Spring源码解析系列】 BeanFactoryPostProcessor</p><p class="is-full-height is-flex-shrink-0 is-flex is-align-items-center is-justify-content-center">点击返回顶部</p></div></h3><aside class="is-flex-shrink-0"><h3 class="is-inline-block"><a href="/blog/">首页</a></h3><h3 class="is-inline-block"><a href="/blog/about">关于</a></h3><h3 class="is-inline-block"><a href="/blog/archives">归档</a></h3></aside></div></header><header class="is-flex header-widget is-flex-shrink-0 is-align-items-center is-justify-content-center is-hidden-tablet"><h3 class="is-inline-block"><a href="/blog/">首页</a></h3><h3 class="is-inline-block"><a href="/blog/about">关于</a></h3><h3 class="is-inline-block"><a href="/blog/archives">归档</a></h3></header><main><main class="container is-max-widescreen content section post-page pt-4 px-4"><div class="columns is-flex-desktop is-justify-content-center is-flex-direction-row-reverse"><div class="column is-3 is-hidden-mobile"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AE%9A%E4%B9%89"><span class="toc-text">定义</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E7%9B%AE%E7%9A%84"><span class="toc-text">使用目的</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%B7%A5%E4%BD%9C%E6%97%B6%E6%9C%BA"><span class="toc-text">工作时机</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%A4%BA%E4%BE%8B"><span class="toc-text">示例</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1%E3%80%81%E8%87%AA%E5%AE%9A%E4%B9%89BeanPostProcessor"><span class="toc-text">1、自定义BeanPostProcessor</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2%E3%80%81%E8%87%AA%E5%AE%9A%E4%B9%89POJO"><span class="toc-text">2、自定义POJO</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3%E3%80%81%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E6%B3%A8%E5%86%8C"><span class="toc-text">3、配置文件注册</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4%E3%80%81%E5%90%AF%E5%8A%A8%E6%B5%8B%E8%AF%95"><span class="toc-text">4、启动测试</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5%E3%80%81%E7%BB%93%E6%9E%9C%E8%BE%93%E5%87%BA"><span class="toc-text">5、结果输出</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90"><span class="toc-text">源码解析</span></a></li></ol></div><div class="column is-9"><header class="my-4"><a href="/blog/tags/Java"><i class="tag post-item-tag">Java</i></a><a href="/blog/tags/Spring"><i class="tag post-item-tag">Spring</i></a></header><h1 class="mt-0 mb-1 is-family-serif" id="postTitle">【Spring源码解析系列】 BeanFactoryPostProcessor</h1><time class="has-text-grey" datetime="2022-11-30T16:00:00.000Z">2022-12-01</time><article class="mt-2 post-content"><p><img src="https://janedler.oss-cn-beijing.aliyuncs.com/images/spring.png" alt="cover"></p>
<p>本文主要讲述Spring三大扩展功能之：BeanFactoryPostProcessor</p>
<span id="more"></span>

<h2 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h2><p>BeanFactory类型的后置处理器</p>
<h2 id="使用目的"><a href="#使用目的" class="headerlink" title="使用目的"></a>使用目的</h2><p>在BeanFactory标准初始化之后来定制修改BeanFactory的bean内容</p>
<h2 id="工作时机"><a href="#工作时机" class="headerlink" title="工作时机"></a>工作时机</h2><p>此时所有Bean的定义被加载进BeanFactory中，但是Bean的实例未完成创建；</p>
<h2 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h2><h4 id="1、自定义BeanPostProcessor"><a href="#1、自定义BeanPostProcessor" class="headerlink" title="1、自定义BeanPostProcessor"></a>1、自定义BeanPostProcessor</h4><pre><code class="java">/**
 * 自定义BeanPostProcessor实现类
 * BeanPostProcessor接口的作用是：
 * 我们可以通过该接口中的方法在bean实例化、配置以及其他初始化方法前后添加一些我们自己的逻辑
 */
public class MyBeanPostProcessor implements BeanPostProcessor &#123;

    /**
     * 实例化、依赖注入完毕，在调用显示的初始化之前完成一些定制的初始化任务
     * 注意：方法返回值不能为null
     * 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象
     * 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
     */
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException &#123;
        System.out.println(&quot;初始化 before--实例化的bean对象:&quot;+bean+&quot;\t&quot;+beanName);
        // 可以根据beanName不同执行不同的处理操作
        if (bean instanceof User)&#123;
            System.out.println(((User)bean).getName());
        &#125;
        return bean;
    &#125;

    /**
     * 实例化、依赖注入、初始化完毕时执行
     * 注意：方法返回值不能为null
     * 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象
     * 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
     */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException &#123;
        System.out.println(&quot;初始化 after...实例化的bean对象:&quot;+bean+&quot;\t&quot;+beanName);
        // 可以根据beanName不同执行不同的处理操作
        if (bean instanceof User)&#123;
            System.out.println(((User)bean).getName());
        &#125;
        return bean;
    &#125;
    
    //通过配置order指定执行优先级
    //数值越大的优先级越低
    /*@Override
    public int getOrder() &#123;
        // TODO Auto-generated method stub
        return 10;
    &#125;*/
&#125;
</code></pre>
<h4 id="2、自定义POJO"><a href="#2、自定义POJO" class="headerlink" title="2、自定义POJO"></a>2、自定义POJO</h4><pre><code class="java">public class User &#123;

    private int id;

    private String name;

    private String beanName;

    public User()&#123;
        System.out.println(&quot;User 被实例化&quot;);
    &#125;

    public int getId() &#123;
        return id;
    &#125;

    public void setId(int id) &#123;
        this.id = id;
    &#125;

    public String getName() &#123;
        return name;
    &#125;

    public void setName(String name) &#123;
        System.out.println(&quot;设置：&quot;+name);
        this.name = name;
    &#125;

    public String getBeanName() &#123;
        return beanName;
    &#125;

    public void setBeanName(String beanName) &#123;
        this.beanName = beanName;
    &#125;
    /**
     * 自定义的初始化方法
     */
    public void start()&#123;
        System.out.println(&quot;User 中自定义的初始化方法&quot;);
        name = &quot;Hello&quot;;
    &#125;

&#125;
</code></pre>
<h4 id="3、配置文件注册"><a href="#3、配置文件注册" class="headerlink" title="3、配置文件注册"></a>3、配置文件注册</h4><pre><code class="xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
       xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
       xsi:schemaLocation=&quot;
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd&quot;&gt;
    &lt;context:component-scan base-package=&quot;org.janedler&quot;/&gt;

    &lt;bean class=&quot;org.janedler.User&quot; id=&quot;user&quot; init-method=&quot;start&quot;&gt;
        &lt;property name=&quot;name&quot; value=&quot;janedler&quot; /&gt;
    &lt;/bean&gt;

    &lt;!-- 注册处理器 --&gt;
    &lt;bean class=&quot;org.janedler.MyBeanPostProcessor&quot;&gt;&lt;/bean&gt;

&lt;/beans&gt;
</code></pre>
<h4 id="4、启动测试"><a href="#4、启动测试" class="headerlink" title="4、启动测试"></a>4、启动测试</h4><pre><code class="java">@Component
public class MyApplication &#123;
    public static void main( String[] args )
    &#123;
        ApplicationContext ac = new ClassPathXmlApplicationContext(&quot;applicationContext.xml&quot;);
        User user = ac.getBean(User.class);
        System.out.println(user);
    &#125;
&#125;
</code></pre>
<h4 id="5、结果输出"><a href="#5、结果输出" class="headerlink" title="5、结果输出"></a>5、结果输出</h4><pre><code class="bash">初始化 before--实例化的bean对象:org.janedler.MyApplication@6be70a    myApplication
初始化 after...实例化的bean对象:org.janedler.MyApplication@6be70a    myApplication
初始化 before--实例化的bean对象:org.springframework.context.event.EventListenerMethodProcessor@1fc5fb8    org.springframework.context.event.internalEventListenerProcessor
初始化 after...实例化的bean对象:org.springframework.context.event.EventListenerMethodProcessor@1fc5fb8    org.springframework.context.event.internalEventListenerProcessor
初始化 before--实例化的bean对象:org.springframework.context.event.DefaultEventListenerFactory@150efb8    org.springframework.context.event.internalEventListenerFactory
初始化 after...实例化的bean对象:org.springframework.context.event.DefaultEventListenerFactory@150efb8    org.springframework.context.event.internalEventListenerFactory
User 被实例化
设置：janedler
初始化 before--实例化的bean对象:org.janedler.User@7d1d39    user
janedler
User 中自定义的初始化方法
初始化 after...实例化的bean对象:org.janedler.User@7d1d39    user
Hello
org.janedler.User@7d1d39
</code></pre>
<h2 id="源码解析"><a href="#源码解析" class="headerlink" title="源码解析"></a>源码解析</h2><p>Bean被实例化出来后，并且注入属性后，会调用initializeBean方法去初始化Bean，在initializeBean方法中会分别调用BeanPostProcessor接口中的两个方法。<br>AbstarctAutowireCapableBeanFactory::doCreateBean</p>
<pre><code class="java">public interface BeanPostProcessor &#123;
    //实例化、依赖注入完毕，在调用显示的初始化之前完成一些定制的初始化任务
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException &#123;
        return bean;
    &#125;

    //实例化、依赖注入、初始化完毕时执行
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException &#123;
        return bean;
    &#125;
&#125;
</code></pre>
<pre><code class="java">//将Bean实例对象封装，并且Bean定义中配置的属性值赋值给实例对象
populateBean(beanName, mbd, instanceWrapper);
//初始化Bean对象
//在对Bean实例对象生成和依赖注入完成以后，开始对Bean实例对象
//进行初始化，为Bean实例对象应用BeanPostProcessor后置处理器
exposedObject = initializeBean(beanName, exposedObject, mbd);
</code></pre>
<pre><code class="java">protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) &#123;
   // 调用Aware接口方法
   invokeAwareMethods(beanName, bean);

   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) &#123;
      // 调用bean后置处理器的postProcessBeforeInitialization方法
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   &#125;

   try &#123;
      // 初始化bean，调用init方法
      invokeInitMethods(beanName, wrappedBean, mbd);
   &#125;
   catch (Throwable ex) &#123;
      throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
   &#125;
   if (mbd == null || !mbd.isSynthetic()) &#123;
      // 调用bean后置处理器的postProcessAfterInitialization方法
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   &#125;

   return wrappedBean;
&#125;
</code></pre>
</article><section class="jump-container is-flex is-justify-content-space-between my-6"><!-- em is empty placeholder--><a class="button is-default" href="/blog/2022/12/01/Spring/Spring-%E6%A8%A1%E6%9D%BF/" title="【Spring源码解析系列】 Aware"><i class="iconfont icon-prev mr-2 has-text-grey"></i><span class="has-text-weight-semibold">上一页: 【Spring源码解析系列】 Aware</span></a><a class="button is-default" href="/blog/2022/12/01/Spring/Spring%E7%9A%84Bean%E5%AE%9E%E4%BE%8B%E5%8C%96%E7%AD%96%E7%95%A5InstantiationStrategy/" title="【Spring源码解析系列】 Bean实例化策略InstantiationStrategy"><span class="has-text-weight-semibold">下一页: 【Spring源码解析系列】 Bean实例化策略InstantiationStrategy</span><i class="iconfont icon-next ml-2 has-text-grey"></i></a></section><article class="mt-6 comment-container"><script async repo="janedler/blog" src="https://utteranc.es/client.js" issue-term="pathname" theme="preferred-color-scheme"></script></article></div></div></main></main><footer class="is-flex is-flex-direction-column is-align-items-center is-flex-shrink-0 is-family-serif"><section class="sns-container"><!-- Github--><a title="github" target="_blank" rel="noopener nofollow" href="//github.com//janedler"><i class="iconfont icon-github"></i></a><!-- Ins--><!-- RSS--><a title="rss" target="_blank" rel="noopener nofollow" href="/blog/atom.xml"><i class="iconfont icon-rss"></i></a><!-- 知乎--><!-- 领英--><!-- 脸书--></section><p><span>Copyright ©</span><span> 田园牧歌(*︶*) 2022</span></p><div class="is-flex is-justify-content-center is-flex-wrap-wrap"><p>Powered by Hexo &verbar;&nbsp;</p><p class="is-flex is-justify-content-center"><a title="Hexo theme author" target="_blank" rel="noopener" href="//github.com/haojen">Theme by Haojen&nbsp;</a></p><div style="margin-top: 2px"><a class="github-button" title="github-button" target="_blank" rel="noopener" href="https://github.com/haojen/hexo-theme-Claudia" data-color-scheme="no-preference: light; light: light; dark: dark;" data-show-count="true"></a></div></div><div><span></span></div></footer><script async defer src="https://buttons.github.io/buttons.js"></script><script src="/blog/js/post.js"></script></body></html>